using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Diagnostics;

using Destra.Tools.DACGenerator.Config;
using System.Reflection;

namespace Destra.Tools.DACGenerator
{
    public partial class MainDialog : Form
    {
        private string m_sql;
        private GeneratorConfig m_generatorConfig;
        private bool m_overrideParameters = false;

        protected DacEntityMethodType dacEntityMethodType
        {
            get
            {
                DacEntityMethodType result = DacEntityMethodType.None;
                if (NoEntityMethodsCheckbox.Checked)
                {
                    result = DacEntityMethodType.None;
                }
                else if (InputEntityMethodsCheckbox.Checked)
                {
                    result = DacEntityMethodType.Input;
                }
                else if (OutputEntityMethodsCheckbox.Checked)
                {
                    result = DacEntityMethodType.Output;
                }
                else if (outputEmbeddedEntityRadioButton.Checked)
                {
                    result = DacEntityMethodType.OutputEmbedded;
                }
                else if (executeScalarRadioButton.Checked)
                {
                    result = DacEntityMethodType.ExecuteScalar;
                }
                else if (executeScalarEntityRadioButton.Checked)
                {
                    result = DacEntityMethodType.ExecuteScalarEntity;
                }
                return result;
            }

            set
            {
                NoEntityMethodsCheckbox.Checked = false;
                InputEntityMethodsCheckbox.Checked = false;
                OutputEntityMethodsCheckbox.Checked = false;
                outputEmbeddedEntityRadioButton.Checked = false;
                executeScalarRadioButton.Checked = false;
                executeScalarEntityRadioButton.Checked = false;

                switch (value)
                {
                    case DacEntityMethodType.None:
                        NoEntityMethodsCheckbox.Checked = true;
                        break;
                    case DacEntityMethodType.Input:
                        InputEntityMethodsCheckbox.Checked = true;
                        break;
                    case DacEntityMethodType.Output:
                        OutputEntityMethodsCheckbox.Checked = true;
                        break;
                    case DacEntityMethodType.OutputEmbedded:
                        outputEmbeddedEntityRadioButton.Checked = true;
                        break;
                    case DacEntityMethodType.ExecuteScalar:
                        executeScalarRadioButton.Checked = true;
                        break;
                    case DacEntityMethodType.ExecuteScalarEntity:
                        executeScalarEntityRadioButton.Checked = true;
                        break;
                }
            }
        }


        public MainDialog(string sql, GeneratorConfig generatorConfig)
        {
            InitializeComponent();

            m_sql = sql;
            m_generatorConfig = generatorConfig;

            tabControl.TabPages.Remove(dacTab);
            tabControl.TabPages.Remove(CachingTab);
            tabControl.TabPages.Remove(entityTab);
            tabControl.TabPages.Remove(loggingTab);

            entityNameTextBox.Enabled = false;
            //generateEntityMethodsCheckBox.CheckedChanged += new EventHandler(generateEntityMethodsCheckBox_CheckedChanged);
            NoEntityMethodsCheckbox.CheckedChanged += new EventHandler(EntityMethods_CheckedChanged);
            InputEntityMethodsCheckbox.CheckedChanged += new EventHandler(EntityMethods_CheckedChanged);
            OutputEntityMethodsCheckbox.CheckedChanged += new EventHandler(EntityMethods_CheckedChanged);
            outputEmbeddedEntityRadioButton.CheckedChanged += new EventHandler(EntityMethods_CheckedChanged);
            executeScalarRadioButton.CheckedChanged += new EventHandler(EntityMethods_CheckedChanged);
            executeScalarEntityRadioButton.CheckedChanged += new EventHandler(EntityMethods_CheckedChanged);

            sqlTextBox.ReadOnly = true;
            sqlTextBox.ScrollBars = ScrollBars.Both;

        }

        void EntityMethods_CheckedChanged(object sender, EventArgs e)
        {
            entityNameTextBox.Enabled = (dacEntityMethodType == DacEntityMethodType.Input) || (dacEntityMethodType == DacEntityMethodType.Output) || (dacEntityMethodType == DacEntityMethodType.ExecuteScalarEntity);

            if (entityNameTextBox.Enabled == false)
            {
                entityNameTextBox.Text = string.Empty;
            }
        }

        public string GetSQL()
        {
            return sqlTextBox.Text;
        }

        public GeneratorConfig GetConfig()
        {
            m_generatorConfig.ConnectionString = this.connectionStringTextBox.Text;

            if (m_generatorConfig is DacGeneratorConfig)
            {
                m_generatorConfig.ClassConfig.Namespace = dacNamespaceTextBox.Text;
                m_generatorConfig.ClassConfig.Class = dacClassTextBox.Text;

                DacGeneratorConfig dacGeneratorConfig = (DacGeneratorConfig)m_generatorConfig;
                //dacGeneratorConfig.EntityName = entityNameTextBox.Text;
                dacGeneratorConfig.DacEntityMethodGeneratorConfig.EntityName = entityNameTextBox.Text;
                dacGeneratorConfig.DacEntityMethodGeneratorConfig.DacEntityMethodType = dacEntityMethodType;

                // set our caching properties
                dacGeneratorConfig.DacEntityMethodGeneratorConfig.CachingAdditionalTables = AdditionalCacheTablesTextBox.Text;
                dacGeneratorConfig.DacEntityMethodGeneratorConfig.CachingEnabled = EnableCachingCheckBox.Checked;
                dacGeneratorConfig.DacEntityMethodGeneratorConfig.CachingType = CacheTypeComboBox.Text;

                if (EntityInterfaceTextBox.Enabled)
                {
                    dacGeneratorConfig.DacEntityMethodGeneratorConfig.EntityInterfaces = EntityInterfaceTextBox.Text;
                }
                else
                {
                    dacGeneratorConfig.DacEntityMethodGeneratorConfig.EntityInterfaces = "";
                }

                if (LogicClassCheckbox.Enabled)
                {
                    dacGeneratorConfig.DacEntityMethodGeneratorConfig.GeneratePredicates = PredicatesCheckBox.Checked;
                    dacGeneratorConfig.DacEntityMethodGeneratorConfig.GenerateBusinessLogicClass = LogicClassCheckbox.Checked;
                    dacGeneratorConfig.DacEntityMethodGeneratorConfig.CommandOutputVariables = OutputVariablesTextBox.Text;
                }
                else
                {
                    dacGeneratorConfig.DacEntityMethodGeneratorConfig.GeneratePredicates = false;
                    dacGeneratorConfig.DacEntityMethodGeneratorConfig.GenerateBusinessLogicClass = false;
                    dacGeneratorConfig.DacEntityMethodGeneratorConfig.CommandOutputVariables = "";
                }

                dacGeneratorConfig.RunTimeConnectionStringName = this.RuntimeConnectionStringNameTextBox.Text;

                if (commandTimeoutTextBox.Text.Length > 0)
                {
                    dacGeneratorConfig.CommandTimeout = Convert.ToInt32(commandTimeoutTextBox.Text);
                }
                else
                {
                    dacGeneratorConfig.CommandTimeout = null;
                }
            }
            else
            {
                m_generatorConfig.ClassConfig.Namespace = entityNamespaceTextBox.Text;
                m_generatorConfig.ClassConfig.Class = entityClassTextBox.Text;

                if (m_generatorConfig is EntityGeneratorConfig)
                {
                    if (entityClassInterfaceTextBox.Enabled)
                    {
                        (m_generatorConfig as EntityGeneratorConfig).EntityInterfaces = entityClassInterfaceTextBox.Text;
                    }
                    else
                    {
                        (m_generatorConfig as EntityGeneratorConfig).EntityInterfaces = "";
                    }

                    (m_generatorConfig as EntityGeneratorConfig).CreateValidationClass = GenerateValidationClass.Checked;
                    (m_generatorConfig as EntityGeneratorConfig).EntityUsingStatements = EntityUsingStatementsTextBox.Text;
                    (m_generatorConfig as EntityGeneratorConfig).EntityCustomAttributes =
                        EntityClassAttributesTextBox.Text;
                    (m_generatorConfig as EntityGeneratorConfig).CustomAttributes = new List<EntityGeneratorConfig.CustomEntityAttribute>();
                    foreach (DataGridViewRow row in dataGridView1.Rows)
                    {
                        if (row.Cells[0].Value != null && row.Cells[1].Value != null)
                        {
                            (m_generatorConfig as EntityGeneratorConfig).CustomAttributes.Add(new EntityGeneratorConfig.CustomEntityAttribute(row.Cells[0].Value.ToString(), row.Cells[1].Value.ToString()));
                        }
                    }
                }

            }

            return m_generatorConfig;
        }

        private void CheckArgumentMissing(TextBox textBox, string value)
        {
            if (textBox.Text.Length == 0)
            {
                throw new ArgumentException(
                    string.Format("The '{0}' value is missing.", value));
            }
        }

        private void Generate()
        {
            this.DialogResult = DialogResult.OK;

            try
            {
                CheckArgumentMissing(connectionStringTextBox, "Connection String");

                if (m_generatorConfig is DacGeneratorConfig)
                {
                    CheckArgumentMissing(dacNamespaceTextBox, "DAC Namespace");
                    CheckArgumentMissing(dacNamespaceTextBox, "DAC Class");
                    CheckArgumentMissing(RuntimeConnectionStringNameTextBox, "Run Time Connection String Name");

                    if (entityNameTextBox.Enabled == true)
                    {
                        CheckArgumentMissing(entityNameTextBox, "Entity Name");
                    }

                    if (commandTimeoutTextBox.Text.Length > 0)
                    {
                        int commandTimeout;

                        if (int.TryParse(commandTimeoutTextBox.Text, out commandTimeout) == false)
                        {
                            throw new ArgumentException(
                                "The 'Command Timeout' value is must be an integer.");
                        }
                    }
                }
                else if (m_generatorConfig is EntityGeneratorConfig)
                {
                    CheckArgumentMissing(entityNamespaceTextBox, "Entity Namespace");
                    CheckArgumentMissing(entityClassTextBox, "Entity Class");
                }
            }
            catch (ArgumentException exception)
            {
                MessageBox.Show(
                    this,
                    exception.Message,
                    "Error",
                    MessageBoxButtons.OK,
                    MessageBoxIcon.Error);

                this.DialogResult = DialogResult.None;
            }

            Settings settings = new Settings();
            settings.ConnectionString = connectionStringTextBox.Text;
            if (RuntimeConnectionStringNameTextBox.Visible == true)
            {
                settings.RunTimeConnectionStringName = RuntimeConnectionStringNameTextBox.Text;
            }
            if (m_generatorConfig is DacGeneratorConfig)
            {
                settings.DACNamespace = dacNamespaceTextBox.Text;
            }
            else if (m_generatorConfig is EntityGeneratorConfig)
            {
                settings.EntityNamespace = entityNamespaceTextBox.Text;
            }
            settings.Save();
        }

        private void MainDialog_Load(object sender, EventArgs e)
        {
            versionLabel.Text = "Version " + this.GetType().Assembly.GetName().Version;

            sqlTextBox.Text = m_sql;

            Settings settings = new Settings();

            if (m_generatorConfig is DacGeneratorConfig)
            {
                tabControl.TabPages.Insert(1, dacTab);
                tabControl.TabPages.Insert(2, CachingTab);
                tabControl.SelectedTab = dacTab;

                DacGeneratorConfig dacGeneratorConfig = (DacGeneratorConfig)m_generatorConfig;
                dacEntityMethodType = dacGeneratorConfig.DacEntityMethodGeneratorConfig.DacEntityMethodType;
                if (dacEntityMethodType != DacEntityMethodType.None) entityNameTextBox.Text = dacGeneratorConfig.DacEntityMethodGeneratorConfig.EntityName;

                RuntimeConnectionStringNameTextBox.Text = dacGeneratorConfig.RunTimeConnectionStringName;

                commandTimeoutTextBox.Text = dacGeneratorConfig.CommandTimeout.ToString();

                //if (string.IsNullOrEmpty(dacGeneratorConfig.EntityName) == false)
                //{
                //    generateEntityMethodsCheckBox.Checked = true;
                //    entityNameTextBox.Text = dacGeneratorConfig.EntityName;
                //}

                // set the interfaces
                EntityInterfaceTextBox.Text = dacGeneratorConfig.DacEntityMethodGeneratorConfig.EntityInterfaces;
                LogicClassCheckbox.Checked = dacGeneratorConfig.DacEntityMethodGeneratorConfig.GenerateBusinessLogicClass;
                PredicatesCheckBox.Checked = dacGeneratorConfig.DacEntityMethodGeneratorConfig.GeneratePredicates;

                // set our caching inputs
                AdditionalCacheTablesTextBox.Text = dacGeneratorConfig.DacEntityMethodGeneratorConfig.CachingAdditionalTables;
                EnableCachingCheckBox.Checked = dacGeneratorConfig.DacEntityMethodGeneratorConfig.CachingEnabled;
                CacheTypeComboBox.Text = dacGeneratorConfig.DacEntityMethodGeneratorConfig.CachingType;

                // set our output variables textbox
                OutputVariablesTextBox.Text = dacGeneratorConfig.DacEntityMethodGeneratorConfig.CommandOutputVariables;
            }
            else if (m_generatorConfig is EntityGeneratorConfig)
            {
                tabControl.TabPages.Insert(1, entityTab);
                tabControl.SelectedTab = entityTab;

                EntityUsingStatementsTextBox.Text = (m_generatorConfig as EntityGeneratorConfig).EntityUsingStatements;
                entityClassInterfaceTextBox.Text = (m_generatorConfig as EntityGeneratorConfig).EntityInterfaces;
                GenerateValidationClass.Checked = (m_generatorConfig as EntityGeneratorConfig).CreateValidationClass;
                EntityUsingStatementsTextBox.Text = (m_generatorConfig as EntityGeneratorConfig).EntityUsingStatements;
                EntityClassAttributesTextBox.Text = (m_generatorConfig as EntityGeneratorConfig).EntityCustomAttributes;
            }

            if (string.IsNullOrEmpty(m_generatorConfig.ClassConfig.Namespace))
            {
                dacNamespaceTextBox.Text = settings.DACNamespace;
            }
            else
            {
                dacNamespaceTextBox.Text = m_generatorConfig.ClassConfig.Namespace;
            }
            dacClassTextBox.Text = m_generatorConfig.ClassConfig.Class;

            if (string.IsNullOrEmpty(m_generatorConfig.ClassConfig.Namespace))
            {
                entityNamespaceTextBox.Text = settings.EntityNamespace;
            }
            else
            {
                entityNamespaceTextBox.Text = m_generatorConfig.ClassConfig.Namespace;
            }
            entityClassTextBox.Text = m_generatorConfig.ClassConfig.Class;

            connectionStringTextBox.Text = m_generatorConfig.ConnectionString;

            #region Custom Entity Attributes

            try
            {
                if (m_generatorConfig is EntityGeneratorConfig)
                {
                    List<QueryInfo.Parameter> parameters;
                    List<QueryInfo.OutputColumn> outputColumns;
                    QueryInfo.QueryTables queryTables;

                    QueryInfo queryPlan = new QueryInfo(connectionStringTextBox.Text, GetSQL());
                    queryPlan.Load(out parameters, out outputColumns, out queryTables);

                    foreach (QueryInfo.OutputColumn outcol in outputColumns)
                    {
                        CustomAttributePropertiesDropdownList.Items.Add(outcol.Name);
                    }                    
                    CustomAttributePropertiesDropdownList.SelectedIndex = 0;


                    foreach (EntityGeneratorConfig.CustomEntityAttribute att in (m_generatorConfig as EntityGeneratorConfig).CustomAttributes)
                    {
                        dataGridView1.Rows.Add(att.PropertyName, att.PropertyAttribute);
                    }
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show("Error in displaying the parameters for the entity attributes" + Environment.NewLine + ex.ToString());
            }

            #endregion

        }

        #region Sql Tabl Button Events

        private void PreviewSqlButton_Click(object sender, EventArgs e)
        {
            if (this.connectionStringTextBox.Text.Length == 0)
            {
                MessageBox.Show(
                    this,
                    "You must enter a connection string in order to use SQL Suggestor",
                    string.Empty,
                    MessageBoxButtons.OK,
                    MessageBoxIcon.Exclamation);
            }
            else
            {
                try
                {
                    PreviewSqlDialog dialog = new PreviewSqlDialog(this.connectionStringTextBox.Text, m_sql);
                    dialog.ShowDialog();
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.ToString());
                }
            }
        }


        private void FormatSqlButton_Click(object sender, EventArgs e)
        {
            if (MessageBox.Show(this, "The SqlFormatter may screw up your formatting.\nAre you sure you want to continue?", "Sql Formatter", MessageBoxButtons.YesNo, MessageBoxIcon.Warning) == DialogResult.Yes)
            {
                Formatters.SqlFormatter sqlFormatter = new Formatters.SqlFormatter();
                sqlFormatter.SqlText = sqlTextBox.Text;
                sqlTextBox.Text = sqlFormatter.Format();
            }
        }

        private void sqlSuggestorButton_Click(object sender, EventArgs e)
        {
            if (this.connectionStringTextBox.Text.Length == 0)
            {
                MessageBox.Show(
                    this,
                    "You must enter a connection string in order to use SQL Suggestor",
                    string.Empty,
                    MessageBoxButtons.OK,
                    MessageBoxIcon.Exclamation);
            }
            else
            {
                SqlSuggestorDialog sqlSuggestorDialog =
                    new SqlSuggestorDialog(this.connectionStringTextBox.Text);
                if (sqlSuggestorDialog.ShowDialog(this) == DialogResult.OK)
                {
                    sqlTextBox.Text = sqlSuggestorDialog.SQL;
                }
            }
        }

        #endregion

        private void generateButton_ButtonClick(object sender, EventArgs e)
        {
            Generate();
        }

        private void generateMenuItem_Click(object sender, EventArgs e)
        {
            Generate();
        }

        private void generateOverrideMenuItem_Click(object sender, EventArgs e)
        {
            m_overrideParameters = true;

            Generate();
        }

        public bool OverrideParameters
        {
            get
            {
                return m_overrideParameters;
            }
        }

        #region Radio Button Events

        private void CheckEntityInterfaceTextBoxEnabled()
        {
            LogicClassCheckbox.Enabled = (outputEmbeddedEntityRadioButton.Checked || OutputEntityMethodsCheckbox.Checked);
            PredicatesCheckBox.Enabled = LogicClassCheckbox.Enabled;
            EntityInterfaceTextBox.Enabled = (outputEmbeddedEntityRadioButton.Checked);
        }

        private void outputEmbeddedEntityRadioButton_CheckedChanged(object sender, EventArgs e)
        {
            CheckEntityInterfaceTextBoxEnabled();
        }

        private void executeScalarRadioButton_CheckedChanged(object sender, EventArgs e)
        {
            CheckEntityInterfaceTextBoxEnabled();
        }

        private void NoEntityMethodsCheckbox_CheckedChanged(object sender, EventArgs e)
        {
            CheckEntityInterfaceTextBoxEnabled();
        }

        private void InputEntityMethodsCheckbox_CheckedChanged(object sender, EventArgs e)
        {
            CheckEntityInterfaceTextBoxEnabled();
        }

        private void OutputEntityMethodsCheckbox_CheckedChanged(object sender, EventArgs e)
        {
            CheckEntityInterfaceTextBoxEnabled();
        }

        private void executeScalarEntityRadioButton_CheckedChanged(object sender, EventArgs e)
        {
            CheckEntityInterfaceTextBoxEnabled();
        }

        #endregion

        private void EnableCachingCheckBox_CheckedChanged(object sender, EventArgs e)
        {
            if (!EnableCachingCheckBox.Checked)
            {
                CacheTypeComboBox.SelectedIndex = -1;
            }
        }

        private void ShowQueryTableDependenciesButton_Click(object sender, EventArgs e)
        {
            try
            {

                List<QueryInfo.Parameter> parameters;
                List<QueryInfo.OutputColumn> outputColumns;
                QueryInfo.QueryTables queryTables;

                QueryInfo queryPlan = new QueryInfo(connectionStringTextBox.Text, GetSQL());
                queryPlan.Load(out parameters, out outputColumns, out queryTables);

                string tableNames = "";
                foreach (QueryInfo.QueryTables.Table table in queryTables.Dependencies)
                {
                    tableNames += table.Inline + ", ";
                }
                tableNames = tableNames.Trim();
                tableNames = tableNames.Substring(0, tableNames.Length - 1).Trim();

                MessageBox.Show(tableNames, "Tables used by this Query");
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString());
            }
        }

        private void ExitApplicationButton_Click(object sender, EventArgs e)
        {
            //Application.ExitThread();
            Environment.Exit(0);
        }

        private void AddAttributeButton_Click(object sender, EventArgs e)
        {
            dataGridView1.Rows.Add(CustomAttributePropertiesDropdownList.Text, CustomAttributesTextBox.Text);
            CustomAttributesTextBox.Text = "";
        }

        private void tabControl_KeyUp(object sender, KeyEventArgs e)
        {
            if(e.KeyCode == Keys.Escape)
            {
                this.Close();
            }
        }

        private void label8_Click(object sender, EventArgs e)
        {

        }

    }
}